package com.naspan.utils;

import com.naspan.common.exception.bizExceptionHandle;
import com.naspan.entity.po.FileInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.List;

public class FileUtils {

    /**
     * 根据路径删除指定的目录或文件，无论存在与否
     *
     * @param sPath  要删除的目录或文件
     * @return 删除成功返回 true，否则返回 false。
     */
    private static String matches = "[A-Za-z]:\\\\[^:?\"><*]*";

    public static final Logger logger = LoggerFactory.getLogger(FileUtils.class);

    /**
     * 读取文件
     *
     * @param response
     * @param filePath 读取的文件路径
     */
    public static void readFile(HttpServletResponse response, String filePath) {
        final File file = new File(filePath);
        if (!file.exists()) {
            return;
        }
        try (
                FileInputStream fs = new FileInputStream(filePath);
                OutputStream os = response.getOutputStream()
        ) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = fs.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            logger.error("读取文件:{}失败", file.getName(), e);
            throw new bizExceptionHandle("合并文件" + file.getName() + "出错");
        }
    }


    /**
     * 合并文件
     *
     * @param tempFile       临时文件
     * @param targetFilePath 保存的目标地址
     * @param fileName       文件名
     * @param delSourceFile  是否删除临时文件
     */
    public static void unionFile(File tempFile, String targetFilePath, String fileName, Boolean delSourceFile) {

        try (
                FileChannel targetFileChannel = new FileOutputStream(targetFilePath, true).getChannel();
        ) {
            File[] tempFiles = tempFile.listFiles();
            for (File file : tempFiles) {
                FileChannel blk = new FileInputStream(file).getChannel();
                targetFileChannel.transferFrom(blk, targetFileChannel.size(), blk.size());
                blk.close();
            }
        } catch (Exception e) {
            logger.error("合并文件:{}失败", fileName, e);
            throw new bizExceptionHandle("合并文件" + fileName + "出错");
        } finally {
            if (delSourceFile) {
                deleteFolder(tempFile.getPath());
            }
        }
    }

    /**
     * 删除文件夹
     *
     * @param sPath 被删除目录的文件路径
     */
    public static void deleteFolder(String sPath) {
        boolean matches = sPath.matches(FileUtils.matches);
        if (matches) {
            File file = new File(sPath);
//        // 判断目录或文件是否存在
            if (file.exists()) {
                if (file.isFile()) {  // 为文件时调用删除文件方法
                    deleteFile(sPath);
                } else {  // 为目录时调用删除目录方法
                    deleteDirectory(sPath);
                }
            }
        }
    }

    /**
     * 删除目录（文件夹）以及目录下的文件
     *
     * @param sPath 被删除目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static void deleteDirectory(String sPath) {
        //如果sPath不以文件分隔符结尾，自动添加文件分隔符
        if (!sPath.endsWith(File.separator)) {
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        //如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return;
        }
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            //删除子文件
            if (files[i].isFile()) {
                deleteFile(files[i].getAbsolutePath());
            } //删除子目录
            else {
                deleteDirectory(files[i].getAbsolutePath());
            }
        }
        // 删除当前目录
        if (dirFile.delete()) {
            System.out.println("成功删除目录：" + sPath);
        } else {
            System.out.println("删除目录失败：" + sPath);
        }
    }


    /**
     * 删除单个文件
     *
     * @param sPath 被删除文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static void deleteFile(String sPath) {
        File file = new File(sPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
        }
    }

}
